import axios from 'axios';
import { createAsyncThunk, isFulfilled, isPending } from '@reduxjs/toolkit';
import { cleanEntity } from 'app/shared/util/entity-utils';
import { IQueryParams, createEntitySlice, EntityState, serializeAxiosError } from 'app/shared/reducers/reducer.utils';
import { IActivity, defaultValue } from 'app/shared/model/activity.model';
import { IActivityProperty } from 'app/shared/model/activity-property.model';

const initialState: EntityState<IActivity> = {
  loading: false,
  errorMessage: null,
  entities: [],
  entity: defaultValue,
  updating: false,
  totalItems: 0,
  updateSuccess: false,
};

const apiUrl = 'api/activities';

// Actions

export const getEntities = createAsyncThunk('activity/fetch_entity_list', async ({ page, size, sort }: IQueryParams) => {
  const requestUrl = `${apiUrl}?${sort ? `page=${page}&size=${size}&sort=${sort}&` : ''}cacheBuster=${new Date().getTime()}`;
  return axios.get<IActivity[]>(requestUrl);
});

export const getEntity = createAsyncThunk(
  'activity/fetch_entity',
  async (id: string | number) => {
    const requestUrl = `${apiUrl}/${id}`;
    return axios.get<IActivity>(requestUrl);
  },
  { serializeError: serializeAxiosError },
);

export const createEntity = createAsyncThunk(
  'activity/create_entity',
  async (entity: IActivity, thunkAPI) => {
    const result = await axios.post<IActivity>(apiUrl, cleanEntity(entity));
    thunkAPI.dispatch(getEntities({}));
    return result;
  },
  { serializeError: serializeAxiosError },
);

export const updateEntity = createAsyncThunk(
  'activity/update_entity',
  async (entity: IActivity, thunkAPI) => {
    const result = await axios.put<IActivity>(`${apiUrl}/${entity.id}`, cleanEntity(entity));
    thunkAPI.dispatch(getEntities({}));
    return result;
  },
  { serializeError: serializeAxiosError },
);

export const partialUpdateEntity = createAsyncThunk(
  'activity/partial_update_entity',
  async (entity: IActivity, thunkAPI) => {
    const result = await axios.patch<IActivity>(`${apiUrl}/${entity.id}`, cleanEntity(entity));
    thunkAPI.dispatch(getEntities({}));
    return result;
  },
  { serializeError: serializeAxiosError },
);

export const deleteEntity = createAsyncThunk(
  'activity/delete_entity',
  async (id: string | number, thunkAPI) => {
    const requestUrl = `${apiUrl}/${id}`;
    const result = await axios.delete<IActivity>(requestUrl);
    thunkAPI.dispatch(getEntities({}));
    return result;
  },
  { serializeError: serializeAxiosError },
);

// export const deletePropertyTemp = createAsyncThunk(
//   'activity/delete_property_temp',
//   async (index: number, thunkAPI) => {
//     let state = thunkAPI.getState();
//     const entity = { ...state['activity'].entity };
//     entity.properties = state['activity'].entity.properties.filter((_, idx) => index != idx);
//     return entity;
//   },
//   { serializeError: serializeAxiosError },
// );
//
// export const addPropertyTemp = createAsyncThunk(
//   'activity/add_property_temp',
//   async (property: IActivityProperty, thunkAPI) => {
//     let state = thunkAPI.getState();
//     const entity = { ...state['activity'].entity };
//     entity.properties = [...state['activity'].entity.properties, property];
//
//     return entity;
//   },
//   { serializeError: serializeAxiosError },
// );
//
// export const changePropertyTemp = createAsyncThunk(
//   'activity/change_property_temp',
//   async (data: { pName: string; pValue: string; index: number }, thunkAPI) => {
//     let state = thunkAPI.getState();
//     const entity = { ...state['activity'].entity };
//     entity.properties = [...state['activity'].entity.properties];
//     const newProp = { ...entity.properties[data.index] };
//     if (data.pValue != null) {
//       newProp.propertyValue = data.pValue;
//     } else {
//       newProp.propertyName = data.pName;
//     }
//     entity.properties[data.index] = newProp;
//
//     return entity;
//   },
//   { serializeError: serializeAxiosError },
// );

// slice

export const ActivitySlice = createEntitySlice({
  name: 'activity',
  initialState,
  extraReducers(builder) {
    builder
      .addCase(getEntity.fulfilled, (state, action) => {
        state.loading = false;
        state.entity = action.payload.data;
      })
      .addCase(deleteEntity.fulfilled, state => {
        state.updating = false;
        state.updateSuccess = true;
        state.entity = {};
      })
      // .addMatcher(isFulfilled(deletePropertyTemp, addPropertyTemp, changePropertyTemp), (state, action) => {
      //   const data = action.payload;
      //
      //   return {
      //     ...state,
      //     loading: false,
      //     entity: data,
      //   };
      // })
      .addMatcher(isFulfilled(getEntities), (state, action) => {
        const { data, headers } = action.payload;

        return {
          ...state,
          loading: false,
          entities: data,
          totalItems: parseInt(headers['x-total-count'], 10),
        };
      })
      .addMatcher(isFulfilled(createEntity, updateEntity, partialUpdateEntity), (state, action) => {
        state.updating = false;
        state.loading = false;
        state.updateSuccess = true;
        state.entity = action.payload.data;
      })
      .addMatcher(isPending(getEntities, getEntity), state => {
        state.errorMessage = null;
        state.updateSuccess = false;
        state.loading = true;
      })
      .addMatcher(isPending(createEntity, updateEntity, partialUpdateEntity, deleteEntity), state => {
        state.errorMessage = null;
        state.updateSuccess = false;
        state.updating = true;
      });
  },
});

export const { reset } = ActivitySlice.actions;

// Reducer
export default ActivitySlice.reducer;
